package com.tanhua.server.service;

import com.tanhua.autoconfig.template.OssTemplate;
import com.tanhua.commons.constant.Constants;
import com.tanhua.commons.exception.TanHuaException;
import com.tanhua.dubbo.api.db.UserInfoApi;
import com.tanhua.dubbo.api.mongo.SoundApi;
import com.tanhua.model.db.UserInfo;
import com.tanhua.model.mongo.Sound;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.vo.SoundVo;
import com.tanhua.server.interceptor.UserHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.Calendar;
import java.util.concurrent.TimeUnit;

/**
 * 桃花传音 业务逻辑处理层
 */
@Slf4j
@Service
public class PeachBlossomServer {

    @DubboReference
    private SoundApi soundApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private OssTemplate ossTemplate;

    /**
     * 桃花传音-接收语音（学生实战）
     * 1、从redis获取今日获取推荐语音的次数
     * 2、如果redis为空,设置 key= userId value=3 凌晨0点过期
     * 3、判断value值是否为小于等于0
     * 4、如果value值小于等于0，则返回null，表示次数已经用尽
     * 5、根据 当前用户的 userId 查询 userinfo 获取当前用户的 性别 ，根据性别推荐 sound 语音
     * 6、根据 userId gender 查询 sound表 的 获取一个推荐的 sound
     * 7、根据 sound 的 sid 修改 sound的 state
     * 8、对redis中的value值减一 set
     * 9、构造vo返回
     *
     * @return
     */
    public SoundVo getSound() {
        Long userId = UserHolder.getUserId();
        //1、从redis获取今日获取推荐语音的次数
        String key = Constants.SOUND_GET_USER_KEY + userId;
        String soundMark = stringRedisTemplate.opsForValue().get(key);
        //2、如果redis为空,设置 key= SOUND_GET_USER_KEY+userId value=3 凌晨0点过期
        if (StringUtils.isEmpty(soundMark)) {
            stringRedisTemplate.opsForValue().set(key, "3", getEndTime(), TimeUnit.MILLISECONDS);
            soundMark = "3";
        }
        //3、判断value值是否为小于等于0
        Integer value = Integer.valueOf(soundMark);
        if (value <= 0) {
            //4、如果value值小于等于0，则返回null，表示次数已经用尽
            throw new TanHuaException(ErrorResult.getSound());
        }
        //5、根据 当前用户的 userId 查询 userinfo 获取当前用户的 性别 ，根据性别推荐语音
        UserInfo userInfo = userInfoApi.findById(userId);
        //6、根据 userId gender 查询 sound表 的 获取一个推荐的 sound
        Sound sound = soundApi.getSoundByRecommend(userId, userInfo.getGender(), userInfo.getAge());
        //7、根据 sound 的 sid 修改 sound的 state 为 1 表示已消费
        if (null == sound) {
            throw new TanHuaException(ErrorResult.noSound());
        }
        sound.setState("1");
        soundApi.updateById(sound);
        //9、构造vo返回
        UserInfo info = userInfoApi.findById(sound.getUserId());
        SoundVo vo = SoundVo.init(info, sound);
        vo.setRemainingTimes(value);
        //8、对redis中的value值减一
        value -= 1;
        stringRedisTemplate.opsForValue().set(key, value.toString(), getEndTime(), TimeUnit.MILLISECONDS);
        return vo;
    }

    /**
     * 获取当天的结束时间 单位：毫秒
     *
     * @return
     */
    private static Long getEndTime() {
        Calendar todayEnd = Calendar.getInstance();
        todayEnd.set(Calendar.HOUR_OF_DAY, 23);
        todayEnd.set(Calendar.MINUTE, 59);
        todayEnd.set(Calendar.SECOND, 59);
        todayEnd.set(Calendar.MILLISECOND, 999);
        long currentTimeMillis = System.currentTimeMillis();
        return todayEnd.getTimeInMillis()-currentTimeMillis;
    }

    /**
     * 桃花传音-发送语音（学生实战） 存一条语音到 MongoDB
     * 1、从redis获取今日发语音的次数
     * 2、如果redis为空,设置 key= userId value=3 凌晨0点过期
     * 3、判断value值是否为小于等于0
     * 4、如果value值小于等于0，则返回null，表示次数已经用尽
     * 5、根据 userId 查询 userinfo 获取 gender
     * 6、构造sound 存到 MongoDB
     * 7、最后对redis中的value值减一 set
     *
     * @param soundFile
     */
    public void saveSound(MultipartFile soundFile) {
        Long userId = UserHolder.getUserId();
        //1、从redis获取今日发语音的次数
        String key = Constants.SOUND_SAVE_USER_KEY + userId;
        String soundMark = stringRedisTemplate.opsForValue().get(key);
        //2、如果redis为空,设置 key= SOUND_SAVE_USER_KEY+userId value=3 凌晨0点过期
        if (StringUtils.isEmpty(soundMark)) {
            stringRedisTemplate.opsForValue().set(key, "3", getEndTime(), TimeUnit.MILLISECONDS);
            soundMark = "3";
        }
        //3、判断value值是否为小于等于0
        Integer value = Integer.valueOf(soundMark);
        if (value <= 0) {
            //4、如果value值小于等于0，则抛异常 "今日语音次数已用尽"
            throw new TanHuaException(ErrorResult.saveSound());
        }
        try {
            //5、根据 userId 查询 userinfo 获取 gender
            UserInfo userInfo = userInfoApi.findById(userId);
            //6、调用 oss 上传文件获取 soundUrl
            String soundUrl = ossTemplate.uploadSound(soundFile.getOriginalFilename(), soundFile.getInputStream());
            //7、构造sound 存到 MongoDB
            Sound sound = new Sound();
            sound.setUserId(userId);
            sound.setGender(userInfo.getGender());
            sound.setAge(userInfo.getAge());
            sound.setSoundUrl(soundUrl);
            sound.setCreated(System.currentTimeMillis());
            soundApi.saveSound(sound);
            //8、对redis中的value值减一 set
            value -= 1;
            stringRedisTemplate.opsForValue().set(key, value.toString(), getEndTime(), TimeUnit.MILLISECONDS);
        } catch (IOException e) {
            throw new TanHuaException("发送语音失败,请长按发送语音键！");
        }
    }
}
